using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using WalkingTec.Mvvm.Core;
using HengTong.Model.Db;
using System.Reflection;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
using HengTong.Model.Db.System;
using HengTong.Model.Interfaces;
using TiaoTaoHelper.Wtm.Interfaces;

namespace HengTong.Model.Services;

/// <summary>
/// 编码生成服务
/// </summary>
public class CodeGeneratorService(WTMContext wtm)
{
    /// <summary>
    /// 根据单据模型名称生成编码
    /// </summary>
    /// <param name="modelName">单据模型名称，如：SysPerson、SysOrg等</param>
    /// <param name="businessId">业务单据ID（可选）</param>
    /// <param name="operatorName">操作人（可选）</param>
    /// <returns>生成的编码</returns>
    public async Task<string> GenerateCodeAsync(string modelName, Guid? businessId = null, string operatorName = null)
    {
        if (string.IsNullOrEmpty(modelName))
            throw new ArgumentException("单据模型名称不能为空", nameof(modelName));
        
        // 查找对应的编码规则
        var codeRule = await wtm.DC.Set<SysCodeRule>()
            .AsNoTracking()
            .Where(x => x.CodeType == modelName && x.IsEnabled)
            .OrderBy(x => x.Sort)
            .FirstOrDefaultAsync();

        if (codeRule == null)
            throw new InvalidOperationException($"未找到模型 {modelName} 的编码规则或规则已禁用");

        // 检查是否需要重置序号
        await CheckAndResetSerialAsync(codeRule);

        // 生成新的序号
        codeRule.CurrentSerial++;
        codeRule.LastGenerateTime = DateTime.Now;

        // 生成完整编码
        var generatedCode = BuildCode(codeRule);

        // 保存编码规则状态
        wtm.DC.UpdateEntity(codeRule);

        // 记录生成历史
        var history = new SysCodeHistory
        {
            CodeRuleId = codeRule.ID,
            GeneratedCode = generatedCode,
            BusinessId = businessId,
            BusinessType = modelName,
            SerialNumber = codeRule.CurrentSerial,
            GenerateTime = DateTime.Now,
            Operator = operatorName,
            TenantCode = codeRule.TenantCode
        };

        wtm.DC.AddEntity(history);
        await wtm.DC.SaveChangesAsync();

        return generatedCode;
    }

    /// <summary>
    /// 获取指定模型的下一个编码预览（不实际生成）
    /// </summary>
    /// <param name="modelName">单据模型名称</param>
    /// <returns>下一个编码预览</returns>
    public async Task<string> PreviewNextCodeAsync(string modelName)
    {
        if (string.IsNullOrEmpty(modelName))
            throw new ArgumentException("单据模型名称不能为空", nameof(modelName));

        var codeRule = await wtm.DC.Set<SysCodeRule>()
            .AsNoTracking()
            .Where(x => x.CodeType == modelName && x.IsEnabled)
            .OrderBy(x => x.Sort)
            .FirstOrDefaultAsync();

        if (codeRule == null)
            throw new InvalidOperationException($"未找到模型 {modelName} 的编码规则或规则已禁用");

        // 创建临时规则对象用于预览
        var previewRule = new SysCodeRule
        {
            Prefix = codeRule.Prefix,
            DateFormat = codeRule.DateFormat,
            SerialLength = codeRule.SerialLength,
            Suffix = codeRule.Suffix,
            CurrentSerial = await GetNextSerialNumberAsync(codeRule)
        };

        return BuildCode(previewRule);
    }

    /// <summary>
    /// 检查并重置序号（如果需要）
    /// </summary>
    private Task CheckAndResetSerialAsync(SysCodeRule codeRule)
    {
        var now = DateTime.Now;
        var shouldReset = false;

        switch (codeRule.ResetRule)
        {
            case CodeResetRule.Never:
                return Task.CompletedTask;
            
            case CodeResetRule.Daily:
                shouldReset = codeRule.LastResetTime?.Date != now.Date;
                break;
            
            case CodeResetRule.Monthly:
                shouldReset = codeRule.LastResetTime?.Year != now.Year || 
                             codeRule.LastResetTime?.Month != now.Month;
                break;
            
            case CodeResetRule.Yearly:
                shouldReset = codeRule.LastResetTime?.Year != now.Year;
                break;
        }

        if (shouldReset)
        {
            codeRule.CurrentSerial = 0;
            codeRule.LastResetTime = now;
        }

        return Task.CompletedTask;
    }

    /// <summary>
    /// 获取下一个序号（用于预览）
    /// </summary>
    private async Task<int> GetNextSerialNumberAsync(SysCodeRule codeRule)
    {
        var tempRule = new SysCodeRule
        {
            ResetRule = codeRule.ResetRule,
            CurrentSerial = codeRule.CurrentSerial,
            LastResetTime = codeRule.LastResetTime
        };

        await CheckAndResetSerialAsync(tempRule);
        return tempRule.CurrentSerial + 1;
    }

    /// <summary>
    /// 构建完整编码
    /// </summary>
    private string BuildCode(SysCodeRule codeRule)
    {
        var code = "";

        // 添加前缀
        if (!string.IsNullOrEmpty(codeRule.Prefix))
            code += codeRule.Prefix;

        // 添加日期格式
        if (!string.IsNullOrEmpty(codeRule.DateFormat))
            code += DateTime.Now.ToString(codeRule.DateFormat);

        // 添加序号（补零）
        code += codeRule.CurrentSerial.ToString().PadLeft(codeRule.SerialLength, '0');

        // 添加后缀
        if (!string.IsNullOrEmpty(codeRule.Suffix))
            code += codeRule.Suffix;

        return code;
    }

    /// <summary>
    /// 检查编码是否已存在
    /// </summary>
    /// <param name="code">要检查的编码</param>
    /// <returns>是否存在</returns>
    public async Task<bool> IsCodeExistAsync(string code)
    {
        return await wtm.DC.Set<SysCodeHistory>()
            .AnyAsync(x => x.GeneratedCode == code);
    }

    /// <summary>
    /// 获取指定模型的编码规则
    /// </summary>
    /// <param name="modelName">单据模型名称</param>
    /// <returns>编码规则</returns>
    public async Task<SysCodeRule> GetCodeRuleAsync(string modelName)
    {
        return await wtm.DC.Set<SysCodeRule>()
            .AsNoTracking()
            .Where(x => x.CodeType == modelName && x.IsEnabled)
            .OrderBy(x => x.Sort)
            .FirstOrDefaultAsync();
    }
    
    /// <summary>
    /// 获取所有实现IDataPrivilege接口的类，并提取Display属性，返回TreeSelectListItem列表
    /// </summary>
    /// <returns></returns>
    public List<TreeSelectListItem> GetDataPrivilegeClassesAsTreeSelectList()
    {
        // 获取当前程序集中所有实现IDataPrivilege接口的类型
        var types = typeof(CodeGeneratorService).Assembly
            .GetTypes()
            .Where(t => t.IsClass && !t.IsAbstract && typeof(IDataPrivilegeEntity).IsAssignableFrom(t))
            .ToList();

        // 创建分组字典
        var groupDict = new Dictionary<string, List<TreeSelectListItem>>();

        foreach (var type in types)
        {
            // 获取类上的Display属性
            var displayAttr = type.GetCustomAttribute<DisplayAttribute>();
            
            if (displayAttr != null)
            {
                var groupName = displayAttr.GroupName ?? "其他表单";
                
                // 创建TreeSelectListItem
                var item = new TreeSelectListItem
                {
                    Id = type.FullName,
                    Value = type.Name,
                    Text = displayAttr.Name ?? type.Name,
                    Tag = displayAttr.Description ?? "",
                    Children = new List<TreeSelectListItem>(),
                    Expended = false
                };

                // 按分组添加到字典
                if (!groupDict.ContainsKey(groupName))
                {
                    groupDict[groupName] = new List<TreeSelectListItem>();
                }
                
                groupDict[groupName].Add(item);
            }
        }

        // 构建树形结构
        var result = new List<TreeSelectListItem>();
        
        foreach (var group in groupDict.OrderBy(x => x.Key))
        {
            var groupItem = new TreeSelectListItem
            {
                Id = $"Group_{group.Key}",
                Value = group.Key,
                Text = group.Key,
                Tag = $"包含 {group.Value.Count} 个表单",
                Children = group.Value.OrderBy(x => x.Text).ToList(),
                Expended = true
            };
            
            result.Add(groupItem);
        }

        return result;
    }
}

